#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>

#define SIZE 512 
#define ZERO '\0'
#define SEP " "
#define NUM 32
#define SkipPath(p) do{ p+=(strlen(p)-1); while(*p!='/') p--; }while(0)

// 这里为了方便就直接定义环境变量了
char cwd[SIZE*2];


// getusername

const char* GetUserName()
{
  const char* name=getenv("USER");
  if(name==NULL) return "none";
  return name;
}
//gethostname

const char* GetHostName()
{
  const char* hostname=getenv("HOSTNAME");
  if(hostname==NULL) return "NONE";
  return hostname;
}
//getcwd

const char* GetCwd()
{
  const char* cwd=getenv("PWD");
  if(cwd==NULL) return"NONE";
  return cwd;
}

void MakeCommamdLineAndPrint()
{
  char line[SIZE];
  const char* username=GetUserName();
  const char* hostname=GetHostName();
  const char* cwd=GetCwd();

  SkipPath(cwd);
  snprintf(line,sizeof(line),"[%s@%s %s]: ",username,hostname, strlen(cwd)==1 ? "/" : cwd+1);
  printf("%s",line);
  fflush(stdout);
}
 int GetuserCommand(char command[],size_t n)
{
  char * s=fgets(command,n,stdin);
  if(s==NULL) return -1;
  command[strlen(command)-1]=ZERO;
  return strlen(command);
}

char * gArgv[NUM];
void SplitCommand(char command[],size_t n)
{
  (void)n;
  //"ls -a -l -n" -> "ls" "-a" "-l" "-n"
  gArgv[0]=strtok(command,SEP); 
  int idex=1;
  while((gArgv[idex++]=strtok(NULL,SEP)));
}

void Die()
{
  exit(1);
}

void  ExecuteCommand()
{  
  pid_t id=fork();
  if(id<0) Die();
  else if(id==0)
  {
    //child
    execvp(gArgv[0],gArgv);
    exit(errno);
  }
  else
  {
    // father
    int status=0;
    pid_t rid=waitpid(id,&status,0);
    if(rid>0)
    {
      //
    }
  }
}

const char* GetHome()
{
  const char * home=getenv("Home");
  if(home) return "/root";
  return home;
}

void Cd()
{
  const char * path=gArgv[1];
  if(path==NULL) path=GetHome();

  //path一定存在
  chdir(path);

  // 刷新环境变量
  char temp[SIZE*2];
  getcwd(temp,sizeof(temp));
  snprintf(cwd,sizeof(cwd),"PWD=%s",temp);
  putenv(cwd);
}  

int CheckBuild()
{
  int yes=0;
  const char * enter_cmd=gArgv[0];
  if(strcmp(enter_cmd,"cd")==0)
  {
    yes=1;
    Cd();
  }
  return yes;
}



int main()
{
  int quit=0;
  while(!quit)
  {
    //printf("name: %s\n",GetUserName());
  
    // 1.输出一个命令行
    MakeCommamdLineAndPrint();

    // 2.获取用户命令字符串
    char usercommand[SIZE];
    int n=GetuserCommand(usercommand,sizeof(usercommand));
    if(n<=0) return 1;

    // 3.命令行字符串分割
    SplitCommand(usercommand,sizeof(usercommand));

    // 4.检查是否是内建命令
    n=CheckBuild();
    if(n) continue;

    // n.执行代码
    ExecuteCommand();


  }

  return 0;
}




















